package com.zc.mychart.chart;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Matrix;
import android.graphics.PointF;
import androidx.core.content.ContextCompat;
import android.util.AttributeSet;
import android.view.MotionEvent;

import com.github.mikephil.charting.charts.CombinedChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarData;
import com.github.mikephil.charting.data.BarDataSet;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.CandleEntry;
import com.github.mikephil.charting.data.CombinedData;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.renderer.CombinedChartRenderer;
import com.zc.mychart.R;
import com.zc.mychart.model.BuySellSignalEntrys;
import com.zc.mychart.model.KDJEntrys;
import com.zc.mychart.model.KViewMode;
import com.zc.mychart.model.LineType;
import com.zc.mychart.model.MACDEntrys;
import com.zc.mychart.model.RSIEntrys;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2018/2/26 0026.
 */

public class MyBarChart extends CombinedChart {
    private Context mContext;
    private final float MIN_VISIBLE_COUNT = 20f;
    private float xVisibleRange = 40f;
    private float lowX = 0f;

    private int bgColor;
    private int lineColor;
    private int textColor;

    private YAxis mYAxis;
    private List<CandleEntry> candleEntryList = new ArrayList<>();
    private LineType currentType = LineType.MACD;
    private MACDEntrys macdEntrys;
    private KDJEntrys kdjEntrys;
    private RSIEntrys rsiEntrys;
    private BuySellSignalEntrys mSignalEntries;
    private KViewMode mKlineMode = KViewMode.MODE_KLINE;

    public MyBarChart(Context context) {
        super(context);
        mContext = context;
    }

    public MyBarChart(Context context, AttributeSet attrs) {
        super(context, attrs);
        mContext = context;
    }

    public MyBarChart(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        mContext = context;
    }

    public void setLightBg() {
        lineColor = ContextCompat.getColor(mContext, R.color.mychart_gray_k_line);
        bgColor = ContextCompat.getColor(mContext, R.color.mychart_white_background);
        textColor = ContextCompat.getColor(mContext, R.color.mychart_text_gray_01);
        setColors();
    }

    public void setDarkBg(KViewMode mKlineMode) {
        lineColor = ContextCompat.getColor(mContext, R.color.mychart_k_line);
        if (mKlineMode == KViewMode.MODE_KLINE) {
            bgColor = ContextCompat.getColor(mContext, R.color.mychart_background);
        } else {
            bgColor = ContextCompat.getColor(mContext, R.color.mychart_train_camp_bg);
        }
        textColor = ContextCompat.getColor(mContext, R.color.mychart_white);
        setColors();
    }

    private void setColors() {
        setBackgroundColor(bgColor);
        setBorderColor(lineColor);
        mAxisLeft.setTextColor(textColor);
        mLegend.setTextColor(textColor);
    }

    @Override
    protected void init() {
        super.init();
        mRenderer = new MyCombinedChartRenderer(this, mAnimator, mViewPortHandler);
        mAxisRendererLeft = new MyYAxisRender(mViewPortHandler, mAxisLeft, mLeftAxisTransformer);
        mLegendRenderer = new MyLegendRenderer(mViewPortHandler, mLegend);
        lightListener = new MyKChart.HighLightListener() {
            @Override
            public void onHighLightX(int x) {
                updateDataLabel(x);
            }
        };
    }

    public void initView() {
        lineColor = ContextCompat.getColor(mContext, R.color.mychart_k_line);
        bgColor = ContextCompat.getColor(mContext, R.color.mychart_background);
        textColor = ContextCompat.getColor(mContext, R.color.mychart_white);
        setMinOffset(0f);
        setDrawBorders(true);
        setBorderColor(lineColor);
        setBorderWidth(1f);
        setPinchZoom(true);
        setScaleYEnabled(false);
        setAutoScaleMinMaxEnabled(true);
        setNoDataText("");
        getDescription().setEnabled(false);
        setBackgroundColor(bgColor);
        setDragDecelerationFrictionCoef(0.95f);
        setDoubleTapToZoomEnabled(false);

        mXAxis.setDrawAxisLine(false);
        mXAxis.setDrawGridLines(false);
        mXAxis.setDrawLabels(false);
        mXAxis.setPosition(XAxis.XAxisPosition.BOTTOM);

        mYAxis = getAxisLeft();
        mYAxis.setTextSize(8);

        mAxisLeft.setSpaceTop(0f);
        mAxisLeft.setDrawAxisLine(false);
        mAxisLeft.setDrawGridLines(false);
        mAxisLeft.setTextColor(textColor);
        mAxisLeft.setLabelCount(3);
        mAxisLeft.setPosition(YAxis.YAxisLabelPosition.INSIDE_CHART);

        mAxisRight.setEnabled(false);
        mLegend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP);
        mLegend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.LEFT);
        mLegend.setOrientation(Legend.LegendOrientation.HORIZONTAL);
        mLegend.setDrawInside(true);
        mLegend.setForm(Legend.LegendForm.LINE);
        mLegend.setTextColor(textColor);
        mLegend.setXOffset(50f);
    }

    @SuppressLint("DefaultLocale")
    public void setBarData(LineType type, List<CandleEntry> list, boolean isReset) {
        if (list != null && list.size() > 0) {
            this.currentType = type;
            this.candleEntryList = list;
            float xRange = getVisibleXRange();
            if (xRange != 0) {
                xVisibleRange = xRange;
            }
            lowX = getLowestVisibleX();
            resetTracking();
            CombinedData combinedData = new CombinedData();
            LineData lineData = new LineData();
            mYAxis.removeAllLimitLines();
            mYAxis.resetAxisMaximum();
            mYAxis.resetAxisMinimum();
            switch (type) {
                case MACD:
                    setDrawOrder(new DrawOrder[]{DrawOrder.BAR, DrawOrder.LINE});
                    macdEntrys = new MACDEntrys(list);
                    BarData barData = generateBarData(macdEntrys.getMACDs(), macdEntrys.getBarColors(), "MACD");
                    String difLabel = "DIF=" + String.format("%.2f", macdEntrys.getDIFs().get(macdEntrys.getDIFs().size() - 1).getY());
                    String deaLabel = "DEA=" + String.format("%.2f", macdEntrys.getDEAs().get(macdEntrys.getDEAs().size() - 1).getY());
                    lineData.addDataSet(generateLineDataSet(macdEntrys.getDIFs(), ContextCompat.getColor(mContext, R.color.mychart_k_line_macd_dif), difLabel));
                    lineData.addDataSet(generateLineDataSet(macdEntrys.getDEAs(), ContextCompat.getColor(mContext, R.color.mychart_k_line_macd_dea), deaLabel));
                    combinedData.setData(barData);
                    combinedData.setData(lineData);
                    break;
                case KDJ:
                    setDrawOrder(new DrawOrder[]{DrawOrder.LINE});
                    kdjEntrys = new KDJEntrys(list);
                    String kLabel = "K=" + String.format("%.2f", kdjEntrys.getKs().get(kdjEntrys.getKs().size() - 1).getY());
                    String dLabel = "D=" + String.format("%.2f", kdjEntrys.getDs().get(kdjEntrys.getDs().size() - 1).getY());
                    String jLabel = "J=" + String.format("%.2f", kdjEntrys.getJs().get(kdjEntrys.getJs().size() - 1).getY());
                    lineData.addDataSet(generateLineDataSet(kdjEntrys.getKs(), ContextCompat.getColor(mContext, R.color.mychart_k_line_kdj_k), kLabel));
                    lineData.addDataSet(generateLineDataSet(kdjEntrys.getDs(), ContextCompat.getColor(mContext, R.color.mychart_k_line_kdj_d), dLabel));
                    lineData.addDataSet(generateLineDataSet(kdjEntrys.getJs(), ContextCompat.getColor(mContext, R.color.mychart_k_line_kdj_j), jLabel));
                    combinedData.setData(lineData);
                    break;
                case RSI:
                    setDrawOrder(new DrawOrder[]{DrawOrder.LINE});
                    rsiEntrys = new RSIEntrys(list);
                    String r6Label = "R6=" + String.format("%.2f", rsiEntrys.getRSI6s().get(rsiEntrys.getRSI6s().size() - 1).getY());
                    String r12Label = "R12=" + String.format("%.2f", rsiEntrys.getRSI12s().get(rsiEntrys.getRSI12s().size() - 1).getY());
                    String r24Label = "R24=" + String.format("%.2f", rsiEntrys.getRSI24s().get(rsiEntrys.getRSI24s().size() - 1).getY());
                    lineData.addDataSet(generateLineDataSet(rsiEntrys.getRSI6s(), ContextCompat.getColor(mContext, R.color.mychart_k_line_rsi6), r6Label));
                    lineData.addDataSet(generateLineDataSet(rsiEntrys.getRSI12s(), ContextCompat.getColor(mContext, R.color.mychart_k_line_rsi12), r12Label));
                    lineData.addDataSet(generateLineDataSet(rsiEntrys.getRSI24s(), ContextCompat.getColor(mContext, R.color.mychart_k_line_rsi24), r24Label));
                    combinedData.setData(lineData);
                    break;
                case MMXH:
                    setDrawOrder(new DrawOrder[]{DrawOrder.LINE});
                    mSignalEntries = new BuySellSignalEntrys(list);
                    String label = "趋势线=" + String.format("%.2f", mSignalEntries.getSignalList().get(mSignalEntries.getSignalList().size() - 1).getY());
//                            + " 压力线=3.5 支撑线=0.3 多空均衡线=1.6";
                    lineData.addDataSet(generateLineDataSet(mSignalEntries.getSignalList(), ContextCompat.getColor(mContext, R.color.mychart_k_line_rsi6), label));
                    LimitLine greenLine = new LimitLine(3.5f);
                    greenLine.setLineColor(ContextCompat.getColor(mContext, R.color.mychart_fall_green));
                    greenLine.setLineWidth(0.5f);
                    LimitLine redLine = new LimitLine(0.3f);
                    redLine.setLineColor(ContextCompat.getColor(mContext, R.color.mychart_k_line_rsi12));
                    redLine.setLineWidth(0.5f);
                    LimitLine grayLine = new LimitLine(1.6f);
                    grayLine.setLineColor(ContextCompat.getColor(mContext, R.color.mychart_dark_high_light_line));
                    grayLine.setLineWidth(0.5f);
                    mYAxis.setAxisMaximum(4.8f);
                    mYAxis.setAxisMinimum(0);
                    mYAxis.addLimitLine(greenLine);
                    mYAxis.addLimitLine(redLine);
                    mYAxis.addLimitLine(grayLine);
                    mYAxis.setDrawLimitLinesBehindData(true);
                    mYAxis.setLabelCount(3, false);
                    combinedData.setData(lineData);
                    break;
            }
            setData(combinedData);
            mXAxis.setAxisMinimum(-0.5f);
            mXAxis.setAxisMaximum(list.size() - 0.5f);
            if (isReset) {
                calculateScale();
                moveViewToX(getXChartMax());
            } else {
                invalidate();
            }
        } else {
            clear();
        }
    }

    @Override
    public void setData(CombinedData data) {
        ((CombinedChartRenderer) mRenderer).createRenderers();
        super.setData(data);
    }

    private void calculateScale() {
        setVisibleXRangeMinimum(MIN_VISIBLE_COUNT);
        Matrix save = new Matrix();
        save.setScale(getXRange() / xVisibleRange, 1f);
        mViewPortHandler.refresh(save, this, false);
        calculateOffsets();
    }

    private BarData generateBarData(List<BarEntry> entries, List<Integer> colors, String label) {
        BarDataSet set = new BarDataSet(entries, label);
        set.setColors(colors);
        set.setDrawValues(false);
        set.setHighlightEnabled(false);
        set.setAxisDependency(YAxis.AxisDependency.LEFT);
        BarData barData = new BarData();
        barData.addDataSet(set);
        return barData;
    }

    private LineDataSet generateLineDataSet(List<Entry> entries, int color, String label) {
        LineDataSet set = new LineDataSet(entries, label);
        set.setColor(color);
        set.setLineWidth(0.45f);
        set.setDrawCircles(false);
        set.setDrawCircleHole(false);
        set.setDrawValues(false);
        set.setHighlightEnabled(true);
        set.setHighLightColor(ContextCompat.getColor(mContext, R.color.mychart_high_light_line));
        set.setAxisDependency(YAxis.AxisDependency.LEFT);
        return set;
    }

    private MyKChart.HighLightListener lightListener;

    public MyKChart.HighLightListener getLightListener() {

        return lightListener;
    }

    @Override
    protected void drawMarkers(Canvas canvas) {
        super.drawMarkers(canvas);
        updateDataLabel(-1);
    }

    @SuppressLint("DefaultLocale")
    private void updateDataLabel(int x) {
        try {
            int maxX = Math.round(getHighestVisibleX()) - 1;
            if (x > 0) {
                maxX = x;
            }
            //偏差值
            int offset = 0;
            switch (currentType) {
                case MACD:
                    List<ILineDataSet> dataSets = getLineData().getDataSets();
                    LineDataSet difsDataSet = (LineDataSet) dataSets.get(0);
                    LineDataSet deasDataSet = (LineDataSet) dataSets.get(1);
                    setDataSetLabel(difsDataSet, "DIF=" + String.format("%.2f", getDataForX(macdEntrys.getDIFs(), maxX).getY()));
                    setDataSetLabel(deasDataSet, "DEA=" + String.format("%.2f", getDataForX(macdEntrys.getDEAs(), maxX).getY()));
                    break;
                case KDJ:
                    List<ILineDataSet> kdjDataSets = getLineData().getDataSets();
                    LineDataSet ksDataSet = (LineDataSet) kdjDataSets.get(0);
                    LineDataSet dsDataSet = (LineDataSet) kdjDataSets.get(1);
                    LineDataSet jsDataSet = (LineDataSet) kdjDataSets.get(2);
                    setDataSetLabel(ksDataSet, "K=" + String.format("%.2f", getDataForX(kdjEntrys.getKs(), maxX).getY()));
                    setDataSetLabel(dsDataSet, "D=" + String.format("%.2f", getDataForX(kdjEntrys.getDs(), maxX).getY()));
                    setDataSetLabel(jsDataSet, "J=" + String.format("%.2f", getDataForX(kdjEntrys.getJs(), maxX).getY()));
                    break;
                case RSI:
                    List<ILineDataSet> rsiDataSets = getLineData().getDataSets();
                    LineDataSet r6DataSet = (LineDataSet) rsiDataSets.get(0);
                    LineDataSet r12DataSet = (LineDataSet) rsiDataSets.get(1);
                    LineDataSet r24DataSet = (LineDataSet) rsiDataSets.get(2);
                    setDataSetLabel(r6DataSet, "R6=" + String.format("%.2f", getDataForX(rsiEntrys.getRSI6s(), maxX).getY()));
                    setDataSetLabel(r12DataSet, "R12=" + String.format("%.2f", getDataForX(rsiEntrys.getRSI12s(), maxX).getY()));
                    setDataSetLabel(r24DataSet, "R24=" + String.format("%.2f", getDataForX(rsiEntrys.getRSI24s(), maxX).getY()));
                    break;
                case MMXH:
                    List<ILineDataSet> signalDataSet = getLineData().getDataSets();
                    LineDataSet iLineDataSet = (LineDataSet) signalDataSet.get(0);
                    String label = "趋势线=" + String.format("%.2f", getDataForX(mSignalEntries.getSignalList(), maxX).getY());
//                            + " 压力线=3.5 支撑线=0.3 多空均衡线=1.6";
                    setDataSetLabel(iLineDataSet, label);
                    break;
            }
            notifyDataSetChanged();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    public Entry getDataForX(List<Entry> entries, int x) {
        for (Entry entry : entries) {
            if (entry.getX() == x) {
                return entry;
            }
        }
        return null;
    }

    public void setDataSetLabel(LineDataSet dataSet, String label) {
        dataSet.setLabel(label);
    }

    PointF downPoint = new PointF();

    public boolean onTouchEvent(MotionEvent evt) {
        switch (evt.getAction()) {
            case MotionEvent.ACTION_DOWN:
                downPoint.x = evt.getX();
                downPoint.y = evt.getY();
                break;
            case MotionEvent.ACTION_MOVE:
                if (getScaleX() > 1 && Math.abs(evt.getX() - downPoint.x) > 5) {
                    getParent().requestDisallowInterceptTouchEvent(true);
                }
                break;
        }
        return super.onTouchEvent(evt);
    }
}
